//
//  PSObjectPool.m
//  PrefCore
//
//  Created by Sergey on 5/8/14.
//  Copyright (c) 2014 Play-on-smart. All rights reserved.
//

#import "PSObjectPool.h"

@interface PSObjectPool () {

    PSObjectPoolCreateObject _createObject;
    
    PSLinkedList *_objects;

}

@end

@implementation PSObjectPool

-(instancetype)initWithCreateObject:(PSObjectPoolCreateObject)createObject {
    if (self = [super init]) {
        _objects = [[PSLinkedList alloc] init];
        _createObject = createObject;
    }
    return self;
}

-(void)setCapacity:(NSUInteger)n {
    n = MAX(n, self.objectsOut);
    // Of the following two loops only one will execute
    while (n > _total) {
        // Preallocate
        [self putObject:_createObject()];
        _total++;
    }
    while (n < _total) {
        // Drain
        [self get];
        _total--;
    }
}

-(id<PSListEntry>)get {
    if (_objects.count) {
        return [_objects removeFirst];
    }
    _total++;
    return _createObject();
}

-(void)putObject:(id<PSListEntry>)entry {
    NSAssert(!entry.previous && !entry.next, @"Recycling a current list element.");
    [_objects addFirst:entry];
}

-(void)putList:(PSLinkedList *)list {
    [_objects moveAppend:list];
}

-(NSUInteger)objectsIn {
    return _objects.count;
}

-(NSUInteger)objectsOut {
    return _total - _objects.count;
}

-(NSString*)description {
    return [NSString
        stringWithFormat:@"Pool: %ld/%ld, total=%ld"
    ,   (unsigned long)self.objectsIn
    ,   (unsigned long)self.objectsOut
    ,   (unsigned long)self.total
    ];
}

@end
